/*
 * @Description: 
 * @Author: fhw
 * @Date: 2022-11-28 11:38:16
 */
import { Injectable, UseFilters } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { isEmpty, isNil } from 'ramda';
import { ChatUser } from 'src/chat_user/entities/chat_user.entity';
import { HttpExceptionFilter } from 'src/http-exception.filter';
import { throwHttp } from 'src/utlis';
import { Connection, Repository } from 'typeorm';
import { CreateUserResumeDto } from './dto/index.dto';
import { GetUserResumeInfoDto, UpdateUserImageDto, UpdateUserResumeDto } from './dto/resume.dto';
import { CreateResumeEducationDto, UpdateResumeEducationDto } from './dto/resumeEducation.dto';
import { CreateResumeExperienceDto, UpdateExperienceDto } from './dto/resumeExperience.dto';
import { CreateResumeProjectDto, UpdateResumeProjectDto } from './dto/resumeProject.dto';
import { CreateResumeSkillDto, UpdateResumeSkillDto } from './dto/resumeSkill.dto';
import { CreateResumeSkilltxtDto, UpdateResumeSkilltxtDto } from './dto/resumeSkilltxt.dto';
import { Resume, ResumeEducation, ResumeExperience, ResumeProject, ResumeSkill, ResumeSkilltxt } from './entities/resume.entity';

@Injectable()
export class ResumeService {
  constructor(
    @InjectRepository(Resume) private resumeRepository: Repository<Resume>,
    @InjectRepository(ResumeEducation) private resumeEducationRepository: Repository<ResumeEducation>,
    @InjectRepository(ResumeExperience) private resumeExperienceRepository: Repository<ResumeExperience>,
    @InjectRepository(ResumeProject) private resumeProjectRepository: Repository<ResumeProject>,
    @InjectRepository(ResumeSkill) private resumeSkillRepository: Repository<ResumeSkill>,
    @InjectRepository(ResumeSkilltxt) private resumeSkilltxtRepository: Repository<ResumeSkilltxt>,
    private readonly connection: Connection,
  ) { }
  // 获取简历信息
  @UseFilters(new HttpExceptionFilter())
  async getResumeInfo(params: GetUserResumeInfoDto) {
    try {
      const data = await this.resumeRepository.findOne({
        where: params,
        relations: ['resumeEducation', 'resumeExperience', 'resumeProject', 'resumeSkill', 'resumeSkilltxt'],
      })
      if (data?.resumeProject) {
        data.resumeProject = data?.resumeProject?.map(item => {
          const technology = item.technology ? JSON.parse(item.technology) : [];
          item.technology = technology
          return item
        })
      }
      return data
    } catch (error) {
      throwHttp(error.message)
    }
  }
  // 创建简历
  @UseFilters(new HttpExceptionFilter())
  async createResume(params: CreateUserResumeDto, { chatUser }: { chatUser: ChatUser; }) {
    const { resumeEducation, resumeExperience, resumeProject, resumeSkill, resumeSkilltxt } = params
    const resumeInfo = await this.getResumeInfo({ userId: params.userId })
    if (!isNil(resumeInfo)) {
      throwHttp('该用户已创建简历')
    }
    // 获取连贯并创立新的queryRunner
    const queryRunner = this.connection.createQueryRunner();
    // 应用咱们的新queryRunner建设真正的数据库连
    await queryRunner.connect();
    // 开始事务
    await queryRunner.startTransaction();
    try {
      // 1.创建简历个人信息
      const userResume = new Resume()
      userResume.name = params.name
      userResume.sex = params.sex
      userResume.nativePlace = params.nativePlace
      userResume.mail = params.mail
      userResume.education = params.education
      userResume.phone = params.phone
      userResume.experience = params.experience
      userResume.occupation = params.occupation
      userResume.userImage = params.userImage
      userResume.PDFUrl = params.PDFUrl
      userResume.userId = params.userId
      userResume.user = chatUser
      //应用事务保留到副表
      const result = await queryRunner.manager.getRepository(Resume).save(userResume);
      // 2.创建教育经历
      const rducationAll = resumeEducation.map(item => {
        const rducation = new ResumeEducation()
        rducation.title = item.title
        rducation.major = item.major
        rducation.resumeId = result.id
        rducation.resume = result
        return rducation
      })
      await queryRunner.manager.createQueryBuilder().insert().into(ResumeEducation).values(rducationAll).execute()

      // 3.创建工作经历
      const experienceAll = resumeExperience.map(item => {
        const experience = new ResumeExperience();
        experience.text = item.text
        experience.title = item.title
        experience.resumeId = result.id
        experience.resume = result
        return experience
      })
      await queryRunner.manager
        .createQueryBuilder()
        .insert()
        .into(ResumeExperience)
        .values(experienceAll).execute()

      // 4.创建项目经验
      const projectAll = resumeProject.map(item => {
        const project = new ResumeProject();
        project.title = item.title
        project.describe = item.describe
        project.technology = item.technology
        project.resumeId = result.id
        project.resume = result
        return project
      })
      await queryRunner.manager
        .createQueryBuilder()
        .insert()
        .into(ResumeProject).values(projectAll).execute()

      // 5. 创建技术掌握程度
      const skillAll = resumeSkill.map(item => {
        const skill = new ResumeSkill();
        skill.count = item.count
        skill.title = item.title
        skill.resumeId = result.id
        skill.resume = result
        return skill
      })
      await queryRunner.manager
        .createQueryBuilder()
        .insert()
        .into(ResumeSkill).values(skillAll).execute()

      // 6.创建技术描述
      const skilltxtAll = resumeSkilltxt.map(item => {
        const skilltxt = new ResumeSkilltxt();
        skilltxt.text = item.text
        skilltxt.resumeId = result.id
        skilltxt.resume = result
        return skilltxt
      })
      await queryRunner.manager
        .createQueryBuilder()
        .insert()
        .into(ResumeSkilltxt).values(skilltxtAll).execute()
      await queryRunner.commitTransaction();
      return '创建简历成功'
    } catch (error) {
      // 出错回滚
      console.log('创立失败，勾销事务');
      await queryRunner.rollbackTransaction();
      throwHttp(error.message)
    } finally {
      // 开释
      await queryRunner.release();
    }
  }
  // 更新用户简历信息
  @UseFilters(new HttpExceptionFilter())
  async updateUserResume(params: UpdateUserResumeDto, { chatUser }: { chatUser: ChatUser; }) {
    try {
      const { name, sex, nativePlace, mail, phone, PDFUrl, education, experience, userId, occupation } = params
      const resumeInfo = await this.getResumeInfo({ userId })
      if (isNil(resumeInfo)) {
        // throwHttp('简历不存在')
        this.createResume({
          ...params,
          resumeExperience: [],
          resumeEducation: [],
          resumeProject: [],
          resumeSkilltxt: [],
          resumeSkill: [],
          userImage: '',
        }, { chatUser })
        return
      }
      const result = await this.resumeRepository.createQueryBuilder().update(Resume)
        .set({
          name, sex, nativePlace, mail, phone, PDFUrl, education, experience, occupation
        })
        .where('userId = :userId', { userId })
        .execute()
      if (result.affected) {
        return '更新简历成功'
      }
      throwHttp('更新简历失败')
    } catch (error) {
      throwHttp(error.message)
    }
  }
  // 更新简历头像
  @UseFilters(new HttpExceptionFilter())
  async updateUserImage(params: UpdateUserImageDto) {
    try {
      const { userId, userImage } = params
      const resumeInfo = await this.getResumeInfo({ userId })
      if (isNil(resumeInfo)) {
        throwHttp('简历不存在')
      }
      const result = await this.resumeRepository.createQueryBuilder().update(Resume)
        .set({
          userImage
        })
        .where('userId = :userId', { userId })
        .execute()
      if (result.affected) {
        return '更新头像成功'
      }
      throwHttp('更新头像失败')
    } catch (error) {
      throwHttp(error.message)
    }
  }
  // 创建技术掌握程度
  @UseFilters(new HttpExceptionFilter())
  async createSkill(params: CreateResumeSkillDto[], { resume }: { resume: Resume }) {
    const skillAll = params.map(item => {
      const skill = new ResumeSkill();
      skill.count = item.count
      skill.title = item.title
      skill.resumeId = resume.id
      skill.resume = resume
      return skill
    })
    return await this.resumeSkillRepository
      .createQueryBuilder()
      .insert()
      .into(ResumeSkill).values(skillAll).execute()

  }
  // 更新技能
  @UseFilters(new HttpExceptionFilter())
  async updateSkill(params: UpdateResumeSkillDto) {
    try {
      const { resumeId, userId, resumeSkill } = params
      const resumeInfo = await this.getResumeInfo({ userId, id: resumeId })
      if (isNil(resumeInfo)) {
        throwHttp('简历不存在')
      }
      // 判断更新数据是否存在
      const updateData = resumeSkill.filter(item => !isNil(item.id) && !isEmpty(item.id))
      if (!isEmpty(updateData)) {
        const list = await this.resumeSkillRepository.find({
          where: updateData.map(item => {
            return {
              id: item.id,
              resumeId
            }
          })
        })
        const getIds = list.map(item => item.id)
        const isIds = updateData.filter(item => !getIds.includes(item.id)).map(item => item.id)
        if (!isEmpty(isIds)) {
          throwHttp(`id: ${isIds} 不存在`)
        }
      }
      // 更新
      for (const item of updateData) {
        const { count, title, id } = item
        await this.resumeSkillRepository.createQueryBuilder().update(ResumeSkill)
          .set({
            count, title
          })
          .where('id = :id', { id })
          .execute()
      }
      // 创建
      const createData = resumeSkill.filter(item => isNil(item.id) || isEmpty(item.id))
      if (!isEmpty(createData)) {
        await this.createSkill(createData, { resume: resumeInfo })
      }
      return '更新技能成功'
    } catch (error) {
      throwHttp(error.message)
    }
  }
  // 技术描述
  @UseFilters(new HttpExceptionFilter())
  async createSkilltext(params: CreateResumeSkilltxtDto[], { resume }: { resume: Resume }) {
    const all = params.map(item => {
      const data = new ResumeSkilltxt();
      data.text = item.text
      data.resumeId = resume.id
      data.resume = resume
      return data
    })
    return await this.resumeSkilltxtRepository
      .createQueryBuilder()
      .insert()
      .into(ResumeSkilltxt).values(all).execute()

  }
  @UseFilters(new HttpExceptionFilter())
  async updateSkillText(params: UpdateResumeSkilltxtDto) {
    try {
      const { resumeId, userId, resumeSkilltxt } = params
      const resumeInfo = await this.getResumeInfo({ userId, id: resumeId })
      if (isNil(resumeInfo)) {
        throwHttp('简历不存在')
      }
      // 判断更新数据是否存在
      const updateData = resumeSkilltxt.filter(item => !isNil(item.id) && !isEmpty(item.id))
      if (!isEmpty(updateData)) {
        const list = await this.resumeSkilltxtRepository.find({
          where: updateData.map(item => {
            return {
              id: item.id,
              resumeId
            }
          })
        })
        const getIds = list.map(item => item.id)
        const isIds = updateData.filter(item => !getIds.includes(item.id)).map(item => item.id)
        if (!isEmpty(isIds)) {
          throwHttp(`id: ${isIds} 不存在`)
        }
      }
      // 更新
      for (const item of updateData) {
        const { text, id } = item
        await this.resumeSkilltxtRepository.createQueryBuilder().update(ResumeSkilltxt)
          .set({
            text
          })
          .where('id = :id', { id })
          .execute()
      }
      // 创建
      const createData = resumeSkilltxt.filter(item => isNil(item.id) || isEmpty(item.id))
      if (!isEmpty(createData)) {
        await this.createSkilltext(createData, { resume: resumeInfo })
      }
      return '更新技术描述成功'
    } catch (error) {
      throwHttp(error.message)
    }
  }
  // 工作经验
  @UseFilters(new HttpExceptionFilter())
  async createExperience(params: CreateResumeExperienceDto[], { resume }: { resume: Resume }) {
    const all = params.map(item => {
      const data = new ResumeExperience();
      data.text = item.text
      data.title = item.title
      data.resumeId = resume.id
      data.resume = resume
      data.date = item.date
      return data
    })
    return await this.resumeExperienceRepository
      .createQueryBuilder()
      .insert()
      .into(ResumeExperience).values(all).execute()

  }
  @UseFilters(new HttpExceptionFilter())
  async updateExperience(params: UpdateExperienceDto) {
    try {
      const { resumeId, userId, resumeExperience } = params
      const resumeInfo = await this.getResumeInfo({ userId, id: resumeId })
      if (isNil(resumeInfo)) {
        throwHttp('简历不存在')
      }
      // 判断更新数据是否存在
      const updateData = resumeExperience.filter(item => !isNil(item.id) && !isEmpty(item.id))
      if (!isEmpty(updateData)) {
        const list = await this.resumeExperienceRepository.find({
          where: updateData.map(item => {
            return {
              id: item.id,
              resumeId
            }
          })
        })
        const getIds = list.map(item => item.id)
        const isIds = updateData.filter(item => !getIds.includes(item.id)).map(item => item.id)
        if (!isEmpty(isIds)) {
          throwHttp(`id: ${isIds} 不存在`)
        }
      }
      // 更新
      for (const item of updateData) {
        const { text, date, id } = item
        await this.resumeExperienceRepository.createQueryBuilder().update(ResumeExperience)
          .set({
            text, date
          })
          .where('id = :id', { id })
          .execute()
      }
      // 创建
      const createData = resumeExperience.filter(item => isNil(item.id) || isEmpty(item.id))
      if (!isEmpty(createData)) {
        await this.createExperience(createData, { resume: resumeInfo })
      }
      return '更新工作经验成功'
    } catch (error) {
      throwHttp(error.message)
    }
  }

  // 更新项目
  @UseFilters(new HttpExceptionFilter())
  async createProject(params: CreateResumeProjectDto[], { resume }: { resume: Resume }) {
    const all = params.map(item => {
      const data = new ResumeProject();
      data.describe = item.describe
      data.technology = item.technology
      data.title = item.title
      data.resumeId = resume.id
      data.resume = resume
      return data
    })
    return await this.resumeExperienceRepository
      .createQueryBuilder()
      .insert()
      .into(ResumeProject).values(all).execute()

  }
  @UseFilters(new HttpExceptionFilter())
  async updateProject(params: UpdateResumeProjectDto) {
    try {
      const { resumeId, userId, resumeProject } = params
      const resumeInfo = await this.getResumeInfo({ userId, id: resumeId })
      if (isNil(resumeInfo)) {
        throwHttp('简历不存在')
      }
      // 判断更新数据是否存在
      const updateData = resumeProject.filter(item => !isNil(item.id) && !isEmpty(item.id))
      if (!isEmpty(updateData)) {
        const list = await this.resumeProjectRepository.find({
          where: updateData.map(item => {
            return {
              id: item.id,
              resumeId
            }
          })
        })
        const getIds = list.map(item => item.id)
        const isIds = updateData.filter(item => !getIds.includes(item.id)).map(item => item.id)
        if (!isEmpty(isIds)) {
          throwHttp(`id: ${isIds} 不存在`)
        }
      }
      // 更新
      for (const item of updateData) {
        const { title, describe, technology, id } = item
        await this.resumeProjectRepository.createQueryBuilder().update(ResumeProject)
          .set({
            title, describe, technology: JSON.stringify(technology || []),
          })
          .where('id = :id', { id })
          .execute()
      }
      // 创建
      const createData = resumeProject.filter(item => isNil(item.id) || isEmpty(item.id)).map(item => {
        return {
          ...item,
          technology: JSON.stringify(item.technology || []),
        }
      })
      console.log(createData);

      if (!isEmpty(createData)) {
        await this.createProject(createData, { resume: resumeInfo })
      }
      return '更新项目成功'
    } catch (error) {
      throwHttp(error.message)
    }
  }

  // 更新教育经历
  @UseFilters(new HttpExceptionFilter())
  async createEducation(params: CreateResumeEducationDto[], { resume }: { resume: Resume }) {
    const all = params.map(item => {
      const data = new ResumeEducation();
      data.major = item.major
      data.title = item.title
      data.date = item.date
      data.resumeId = resume.id
      data.resume = resume
      return data
    })
    return await this.resumeExperienceRepository
      .createQueryBuilder()
      .insert()
      .into(ResumeEducation).values(all).execute()

  }
  @UseFilters(new HttpExceptionFilter())
  async updateEducation(params: UpdateResumeEducationDto) {
    try {
      const { resumeId, userId, resumeEducation } = params
      const resumeInfo = await this.getResumeInfo({ userId, id: resumeId })
      if (isNil(resumeInfo)) {
        throwHttp('简历不存在')
      }
      // 判断更新数据是否存在
      const updateData = resumeEducation.filter(item => !isNil(item.id) && !isEmpty(item.id))
      if (!isEmpty(updateData)) {
        const list = await this.resumeEducationRepository.find({
          where: updateData.map(item => {
            return {
              id: item.id,
              resumeId
            }
          })
        })
        const getIds = list.map(item => item.id)
        const isIds = updateData.filter(item => !getIds.includes(item.id)).map(item => item.id)
        if (!isEmpty(isIds)) {
          throwHttp(`id: ${isIds} 不存在`)
        }
      }
      // 更新
      for (const item of updateData) {
        const { title, major, date, id } = item
        await this.resumeEducationRepository.createQueryBuilder().update(ResumeEducation)
          .set({
            title, major, date
          })
          .where('id = :id', { id })
          .execute()
      }
      // 创建
      const createData = resumeEducation.filter(item => isNil(item.id) || isEmpty(item.id))
      if (!isEmpty(createData)) {
        await this.createEducation(createData, { resume: resumeInfo })
      }
      return '更新教育经历成功'
    } catch (error) {
      throwHttp(error.message)
    }
  }
}
